#!/usr/bin/python2.4
#
#Copyright 2009 Google Inc.
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
#

"""Manages unique value sets for sorting column values.

This module provides class ColumnSet, which basically maintains unique value
set for metadata sorting column values. SetManager class is singleton
implementation of Manager, which maintains array of ColumnSet objects, each one
for one sorting column.
"""

import logging


class SetManager(object):
  """Singleton implementation of Manager.

  This class maintains array of ColumnSet objects. Each object represents
  unique value set for one sorting column.
  """

  _setmanager = None

  class Singleton(object):
    """Singleton implementation."""

    def __init__(self):
      self._level_set = {}
      self._level_set[1] = ColumnSet(1)
      self._level_set[2] = ColumnSet(2)
      self._level_set[3] = ColumnSet(3)

  def __init__(self):
    if SetManager._setmanager is None:
      SetManager._setmanager = SetManager.Singleton()
    self.__dict__['_SetManager_instance'] = SetManager._setmanager

  def __getattr__(self, attr):
    return getattr(self._setmanager, attr)

  def __setattr__(self, attr, value):
    return setattr(self._setmanager, attr, value)

  def UpdateColumnSets(self, key, first_sorting_column, second_sorting_column,
                       third_sorting_column):
    """Updates ColumnSet objects for the specified values.

    Args:
      key: Unique string identifier for the specified metadata row.
      first_sorting_column: String value for the first sorting column.
      second_sorting_column: String value for the second sorting column.
      third_sorting_column: String value for the third sorting column.
    """
    column_set_level1 = self._level_set[1]
    column_set_level2 = self._level_set[2]
    column_set_level3 = self._level_set[3]
    column_set_level1.AddValue(first_sorting_column, key)
    column_set_level2.AddValue(second_sorting_column, key)
    column_set_level3.AddValue(third_sorting_column, key)

  def GetUniqueValues(self, level):
    """Returns unique values for the specified sorting column.

    Args:
      level: Level number indicating sorting column.

    Returns:
      Array of unique values for the specified sorting column.
    """
    if level > 3:
      logging.error('Wrong level')
      return None
    level_set = self._level_set[level]
    if level_set:
      return level_set.values
    return None

  def IsSetEmpty(self, level):
    """Returns whether the specified sorting column has no values.

    Args:
      level: Level number indicating sorting column.

    Returns:
      Boolean indicating whether the specified sorting column has no values.
    """
    if level > 3:
      logging.error('wrong level specified (should be <= 3)')
      return True
    column_set = self._level_set[level]
    if not column_set:
      return True
    if len(column_set.values) > 1:
      return False
    if not column_set.values[0]:
      return True
    return False

  def PrintUniqueValues(self):
    """Print unique values of all the sorting columns."""
    for level in range(1, 4):
      column_set = self._level_set[level]
      column_set.PrintSet()

  def Clear(self):
    """Clears all the sorting columns sets."""
    if SetManager._setmanager:
      del self._level_set[1]
      del self._level_set[2]
      del self._level_set[3]
      SetManager._setmanager = None


class ColumnSet(object):
  """Maintains unique value set for one sorting column."""

  def __init__(self, level):
    self.level = level
    self.values = []
    self.set = {}

  def AddValue(self, value, key):
    """Adds value to the unique value set.

    Args:
      value: String value.
      key: Unique string identifier for the metadata row with specified sorting
      column value.
    """
    if value not in self.values:
      self.values.append(value)
      column_value_map = {}
      column_value_map['new_val'] = value
      column_value_map['keys'] = []
      column_value_map['keys'].append(key)
      self.set[value] = column_value_map
    else:
      column_value_map = self.set[value]
      column_value_map['keys'].append(key)

  def UpdateNewValue(self, old_value, new_value):
    """Updates old value with new value in ColumnSet.

    Args:
      old_value: Old string value to be updated.
      new_value: New string value.
    """
    if old_value in self.set:
      column_value_map = self.set[old_value]
      column_value_map.new_value = new_value
    else:
      logging.error(old_value)
      logging.error('ERROR: Not present in unique value set')

  def PrintSet(self):
    """Prints all the unique values from this ColumnSet."""
    logging.debug('Printing values for level %d', self.level)
    for value in self.values:
      logging.debug(value)
